#pragma once
#include<iostream>
#include<string>
#include<functional>
#include<sys/epoll.h>
#include"Connection.hpp"
#include"NoBlock.hpp"
#include"Protocol.hpp"
#include"log.hpp"
#include"EpollServer.hpp"



class IOServer : public Connection {
    public:
        static const int size = 1024;
        IOServer(int sockfd)
        {
            SetNonBlock(sockfd);//设置非阻塞
            SetFd(sockfd);
            SetEvents(EPOLLIN | EPOLLET);
        }
        virtual void _read_callback() override//读事件回调
        {
            //基于ET模式读取所有数据
            while(true){
                char buf[size];
                ssize_t n = recv(_sock_fd, buf, sizeof(buf), 0);
                if(n > 0){//读到数据
                    buf[n] = '\0';
                    Append2Inbuffer(buf);//追加到接收缓冲区

                }else if(n == 0){//对端关闭连接

                    _except_callback();
                    return;
                
                }else{
                    if(errno == EAGAIN || errno == EWOULDBLOCK){//读缓冲区为空
                        break;
                    }else if(errno == EINTR){//信号中断
                        continue;
                    }else{//其他错误
                        _except_callback();
                        return;
                    }
                }
            }
            //本轮数据读完
            std::cout<<GetInbuffer()<<std::endl;
            //通过协议
            std::string result;
            if(_HandleMessage){
                result = _HandleMessage(GetInbuffer());//处理消息,得到结果
            }
            if(!result.empty())
                Append2Outbuffer(result);//将处理得到的结果追加到发送缓冲区

            //处理写的问题
            //1.直接发送
            //2.使能写事件，等待epoll通知
            if(!IsWriteEmpty()){
                
                //发送缓冲区不为空，设置写事件
                GetEpollOwner()->EnableReadWrite(GetFd(), true,true);
            }

        }
        virtual void _write_callback() override//写事件回调
        {
            //直接写
            //因为发送数据前fd所关心的事件都是只关心读的，当读到数据并对此处理完后，得到结果并追加到发送缓冲区，此时再次设置写事件，等待epoll通知
            while(true){
                ssize_t n = send(_sock_fd, _outbuffer.c_str(), _outbuffer.size(), 0);
                if(n > 0){//写成功
                    SplitOutbuffer(n);
                }else if(n==0){
                    //用户发送缓冲区已清空
                    break;
                }else{
                    if(errno == EAGAIN || errno == EWOULDBLOCK){//内核中写缓冲区满
                        break;
                    }else if(errno == EINTR){//被信号中断
                        continue;
                    }else{
                        //其他错误
                        _except_callback();
                        return;
                    }
                }
            }
            //跳出循环，用户级缓冲区已清空或底层缓冲区已写满
            if(!IsWriteEmpty()){
                //发送缓冲区不为空，说明底层缓冲区已满，设置关心写事件
                GetEpollOwner()->EnableReadWrite(GetFd(), true,true);
            }else{
                //底层缓冲区未写满，设置只关心读事件
                GetEpollOwner()->EnableReadWrite(GetFd(), true,false);
            }
            
        }
        virtual void _except_callback() override//异常事件回调
        {
            //异常，关闭链接，从内核中关闭对fd的关心
            LOG(log_level::INFO) << "client quit "<<GetFd();
            GetEpollOwner()->Remove_Connection(GetFd());

        }
        void SetHandleMessage(func_t handle)
        {
            _HandleMessage = handle;
        }
        ~IOServer()
        {}

};